package com.nd.android.musicboxlibrary.ui.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.common.StarAppConfig;
import com.common.StarAppConst;
import com.nd.android.musicboxlibrary.R;
import com.nd.android.musicboxlibrary.business.bean.LyricObject;
import com.nd.android.musicboxlibrary.business.comm.MagicNumber;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 歌词控件 Created 2014年9月11日 下午11:47:46
 * 
 * @version
 * @author zxq
 * @see
 */
public class LyricView extends View implements MagicNumber {
    
    /**
     * 
     * <br>Created 2014年11月28日 上午12:05:46
     * @author       wat.ztag
    */
    @Override
    public void initMagicNumber() {}
    
    // 歌词每行的间隔
    public static final int INTERVAL = 20;
    // 歌词实体
    private TreeMap<Integer, LyricObject> mMapLyric;
    // 歌词在Y轴上的偏移量，此值会根据歌词的滚动变小
    private float mOffsetY;
    // 是否找到歌词文件
    private boolean mHasLyric = false;
    // 当触摸歌词View时，保存为当前触点的Y轴坐标
    private float mTouchY;
    // 是否正在拖动
    private boolean mIsScrolled = false;
    // 保存歌词TreeMap的下标
    private int mLrcIndex = 0;
    // 显示歌词文字的大小值
    private int mTextSize = 0;
    // 屏幕X轴的中点，此值固定，保持歌词在X中间显示
    private int mCenterX;
    // 屏幕Y轴的中点，此值固定，保持歌词在X中间显示
    private int mCenterY = 0;
    // 画笔，用于画不是高亮的歌词
    private Paint mPaint = new Paint();
    // 画笔，用于画高亮的歌词，即当前唱到这句歌词
    private Paint paintHL = new Paint();
    private OnClickListener mOnCListener;
    private boolean mIsPaused = true;
    private float mLastOffset; 
    private static final Pattern PATTERN = Pattern.compile("\\d{2}");

    /**
     * Creates a new instance of LyricView. <br>
     * Created 2014年9月15日 下午11:02:04
     * 
     * @param context
     *            上下文
     */
    public LyricView(Context context) {
        super(context);
        init();
    }

    /**
     * Creates a new instance of LyricView. <br>
     * Created 2014年9月15日 下午11:02:08
     * 
     * @param context
     *            上下文
     * @param attrs
     *            控件参数
     */
    public LyricView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mHasLyric && mMapLyric != null && !mMapLyric.isEmpty()) {
            paintHL.setTextSize(mTextSize);
            mPaint.setTextSize(mTextSize);
            if (StarAppConfig.getBooleanConfig(StarAppConfig.IS_USED_SPECIAL_FONT)) {
                // 如果不需要使用特殊字体，直接返回
                paintHL.setTypeface(StarAppConst.getInstance().getLTXTypeface());
                mPaint.setTypeface(StarAppConst.getInstance().getLTXTypeface());
            }
            LyricObject temp = mMapLyric.get(mLrcIndex);
            drawLrc(canvas, temp, mLrcIndex, paintHL);
            // 画当前歌词之前的歌词
            for (int i = mLrcIndex - 1; i >= 0; i--) {
                temp = mMapLyric.get(i);
                if (mOffsetY + (mTextSize + INTERVAL) * i < 0) {
                    break;
                }
                drawLrc(canvas, temp, i, mPaint);
            }
            // 画当前歌词之后的歌词
            for (int i = mLrcIndex + 1; i < mMapLyric.size(); i++) {
                temp = mMapLyric.get(i);
                if (mOffsetY + (mTextSize + INTERVAL) * i > getBottom()) {
                    break;
                }
                drawLrc(canvas, temp, i, mPaint);
            }
        } else {
            mPaint.setTextSize(n40);
            canvas.drawText(getContext().getString(R.string.mbx_unfind_lyric), mCenterX, mCenterY
                    - n20, mPaint);
        }
    }

    /**
     * 画歌词 Created 2014年9月15日 下午11:02:14
     * 
     * @param canvas
     *            画布
     * @param temp
     *            歌词实体
     * @param index
     *            序号
     * @param paint
     *            画笔
     * @author zxq
     */
    private void drawLrc(Canvas canvas, LyricObject temp, int index, Paint paint) {
        if (temp == null) {
            return;
        }
        canvas.drawText(temp.getLrc(), mCenterX, mOffsetY + (mTextSize + INTERVAL) * index, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float temp = event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (mHasLyric) {
                mIsScrolled = true;
            }
            mTouchY = event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            if (mHasLyric) {
            	int lineHeight = mTextSize + LyricView.INTERVAL - 1;
                mOffsetY = mCenterY - mLrcIndex * (lineHeight);
                float offset = Math.abs(temp - mTouchY);
                if (offset > n10) {
                    mOffsetY += (temp - mTouchY);
                    // 接着上次的位置继续拖动
                    mOffsetY += mLastOffset;
                    // 到顶时不可再拖动
                    if (mOffsetY > mCenterY) {
						mOffsetY = mCenterY;
					} else if (mOffsetY < mCenterY - mMapLyric.size() * lineHeight){
						// 到底时不可再拖动
						mOffsetY = mCenterY - mMapLyric.size() * lineHeight;
					}
                    invalidate();
                }
            }
            break;

        case MotionEvent.ACTION_UP:
        	// 保存上次的拖动位移
            mLastOffset = mOffsetY - mCenterY;
            // 1秒后刷新
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    mIsScrolled = false;
                    if (!mIsPaused) {
                        mOffsetY = mCenterY - mLrcIndex * (mTextSize + LyricView.INTERVAL - 1);
                        postInvalidate();
                        // 将保存的拖动位移清零
                        mLastOffset = 0;
                    }
                }
            }, n1000);
            float offset = Math.abs(temp - mTouchY);
            if (offset < n10 && mOnCListener != null) {
                mIsScrolled = false;
                mOnCListener.onClick(this);
            }
            break;
        default:
            break;
        }
        return true;
    }

    /**
     * 初始化 Created 2014年9月15日 下午11:02:19
     * 
     * @author zxq
     */
    public void init() {
        mTextSize = getContext().getResources().getDimensionPixelSize(R.dimen.mbx_lyric_text_size);
        mMapLyric = new TreeMap<Integer, LyricObject>();
        // 歌词画笔
        mPaint = new Paint();
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(getResources().getColor(R.color.mbx_white));
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setAlpha(n180);

        // 高亮歌词画笔
        paintHL = new Paint();
        paintHL.setTextAlign(Paint.Align.CENTER);
        paintHL.setColor(getResources().getColor(R.color.mbx_font_lyric_pink));
        paintHL.setAntiAlias(true);
        paintHL.setAlpha(n255);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w / 2;
        // mCenterY = h / 2;
        mCenterY = (getTop() + getBottom()) / 2;
        mOffsetY = mCenterY;
    }

    /**
     * 根据歌词里面最长的那句来确定歌词字体的大小 Created 2014-7-17 下午11:27:06
     * 
     * @author zxq
     */
    public void setTextSize() {
        if (!mHasLyric || mMapLyric.isEmpty()) {
            return;
        }
        int max = mMapLyric.get(0).getLrc().length();
        for (int i = 1; i < mMapLyric.size(); i++) {
            LyricObject lrcStr = mMapLyric.get(i);
            if (max < lrcStr.getLrc().length()) {
                max = lrcStr.getLrc().length();
            }
        }
        mTextSize = getWidth() / max;
        int maxSize = getContext().getResources()
                .getDimensionPixelSize(R.dimen.mbx_lyric_text_size);
        if (mTextSize > maxSize) {
            mTextSize = maxSize;
        }
    }

    /**
     * 按当前的歌曲的播放时间，从歌词里面获得那一句 Created 2014-7-17 下午11:27:50
     * 
     * @param time
     *            当前歌曲的播放时间
     * @return 返回当前歌词的索引值
     * @author zxq
     */
    public int selectIndex(int time) {
        if (!mHasLyric) {
            return 0;
        }
        int index = 0;
        for (int i = 0; i < mMapLyric.size(); i++) {
            LyricObject temp = mMapLyric.get(i);
            if (temp != null && temp.getBegintime() < time) {
                ++index;
            }
        }
        mLrcIndex = index - 1;
        if (mLrcIndex < 0) {
            mLrcIndex = 0;
        }
        return mLrcIndex;
    }

    /**
     * 读取歌词文件 Created 2014-7-17 下午11:28:12
     * 
     * @param file
     *            歌词的路径
     * @author zxq
     */
    public void read(String file) {
        TreeMap<Integer, LyricObject> mapRead = new TreeMap<Integer, LyricObject>();
        String data = "";
        try {
            File saveFile = new File(file);
            if (!saveFile.isFile()) {
                mHasLyric = false;
                postInvalidate();
                return;
            }
            mHasLyric = true;

            FileInputStream stream = new FileInputStream(saveFile);
            BufferedReader br = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
            while ((data = br.readLine()) != null) {
                // 将前面的替换成后面的
                data = data.replace("[", "");
                data = data.replace("]", "@");
                // 分隔
                String[] splitData = data.split("@");
                boolean hasContent = !data.endsWith("@");
                int size = splitData.length;
                int count = hasContent ? size - 1 : size;
        		String lrcContent = hasContent ? splitData[size - 1] : "";
        		for (int i = 0; i < count; i++) {
        			String strTemp = splitData[i];
        			strTemp = strTemp.replace(":", ".");
        			strTemp = strTemp.replace(".", "@");
        			String timedata[] = strTemp.split("@");
        			Matcher matcher = PATTERN.matcher(timedata[0]);
        			if (timedata.length >= 2 && matcher.matches()) {
        				int m = Integer.parseInt(timedata[0]);
        				int s = Integer.parseInt(timedata[1]);
        				int ms = timedata.length == 3 ? Integer.parseInt(timedata[2]) : 0;
        				int currTime = (m * n60 + s) * n1000 + ms * n10;
        				LyricObject lyricObject = new LyricObject();
        				lyricObject.setBegintime(currTime);
        				lyricObject.setLrc(lrcContent);
        				// 将currTime当标签 item1当数据 插入TreeMap里
        				mapRead.put(currTime, lyricObject);
        			}
        		}
            }
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
            mHasLyric = false;
            postInvalidate();
            return;
        }

        // 遍历hashmap 计算每句歌词所需要的时间
        mMapLyric.clear();
        Iterator<Integer> iterator = mapRead.keySet().iterator();
        LyricObject oldval = null;
        int i = 0;
        while (iterator.hasNext()) {
            Object ob = iterator.next();
            LyricObject val = (LyricObject) mapRead.get(ob);
            if (oldval == null) {
                oldval = val;
            } else {
                LyricObject item1 = new LyricObject();
                item1 = oldval;
                item1.setTimeline(val.getBegintime() - oldval.getBegintime());
                mMapLyric.put(i, item1);
                i++;
                oldval = val;
            }
            if (!iterator.hasNext()) {
                mMapLyric.put(i, val);
            }
        }
        postInvalidate();
    }

    /**
     * 设置是否可以滚动 Created 2014年9月15日 下午11:02:28
     * 
     * @param isScrolled
     *            是否可以滚动
     * @author zxq
     */
    public void setScrolled(boolean isScrolled) {
        this.mIsScrolled = isScrolled;
    }

    @Override
    public void setOnClickListener(OnClickListener onClickListener) {
        this.mOnCListener = onClickListener;
    }

    /**
     * 设置歌词文字的大小
     * 
     * @param textSize
     *            字体大小
     */
    public void setTextSize(int textSize) {
        mTextSize = textSize;
    }

    /**
     * 更新 Created 2014-7-13 下午10:18:39
     * 
     * @param positon
     *            播放进度
     * @author zxq
     */
    public void update(int positon) {
        if (!mIsScrolled) {
            mOffsetY = mCenterY - selectIndex(positon) * (mTextSize + LyricView.INTERVAL - 1);
            postInvalidate();
        }
    }

    /**
     * @return the mIsPaused
     */
    public boolean isPaused() {
        return mIsPaused;
    }

    /**
     * Created 2014年11月16日 下午7:09:18
     * @param isPaused boolean
     * @author       wat.ztag
    */
    public void setPaused(boolean isPaused) {
        this.mIsPaused = isPaused;
        mLastOffset = 0;
    }
}
